home *** CD-ROM | disk | FTP | other *** search
/ 130 MIDI Tool Box / 130 MIDI Tool Box.iso / tmpu_pas / tpmpu.pas < prev   
Pascal/Delphi Source File  |  1987-06-04  |  5KB  |  104 lines

  1. {  The following is an example and discussion of an interrupt routine routine
  2. written in turbo pascal for use with midi applications on an ibmpcxt with
  3. a roland mpu401 interface.
  4. Prior to utilizing the interrupt routines one must
  5.      1.change the vector address to the offset and code segment  of your
  6.        interrupt routine.The address is 4 bytes beginning at 040(decimal)
  7.        -see below routine irq2_on.
  8.      2.enable irq2  (turn the 2nd byte of port hex 21 to 0 -see irq2_on)
  9. The routine 'never_call_stop_mode_herc' is an example of
  10.   an irq2 routine which is never called by the program directly -
  11.   rather it is called when an irq2 occurs .The mpu401 sends a irq2
  12.   whenever it wants to send a single byte of information so the routine
  13.   is set up to handle one byte at a time only .
  14.   (This particular routine plays a piano keyboard on the screen in real time
  15.   while also printing notes(no time values) on a piano staff on the screen.
  16.   Other procedures are called which handle these functions.
  17.   The mpu401 has been set to stop mode(command hex 8a)prior to activation
  18.   of these routines,but the shell(inline statements) work the same with
  19.   any mode of the mpu401(ie.record,play,overdub).
  20. The interrupt routine
  21.   must begin with the inline statement (which saves the current registers)
  22.   and end with the port statement (eoi to irq controller)  and another inline
  23.   statement (restore registers).
  24.   In between can be turbo pascal code with the following restrictions
  25.   -as outlined in the turbo manual
  26.        1.no access to input/output commands such as write or read -
  27.          though can write directly to screen memory.
  28.        2.only typed constants are allowed -ie variables which have been
  29.        defined initialized to some value.(eg. const mididata :byte=0;
  30.        This is because these variables are stored in the code segment (CS)
  31.        rather than the data segment (DS) which is usually unavailable in
  32.        the interrupt mode.If you really want to access global variables
  33.        you can -according to the turbo manual - store the value of Dseg
  34.        in a constant variable and then use it in the interrupt handler to
  35.        set the ds properly.I have yet to implement this and am not quite
  36.        sure how to (let me know if you have implemented this).
  37. When finsished with the interrupt mode it is neccessary to disable the
  38.   irq2 (via port hex 21) and restore the old vector for irq2.This is done
  39.   in the routine irq2_off.  }
  40. {****************************************************************************}
  41. procedure never_call_stop_mode_herc;
  42.  
  43. begin
  44. inline ($50/$53/$51/$52/$56/$57/$1E/$06/$fb);  {fb=enable further interrupts}
  45.  
  46. mididata:=port[dataport];
  47. if mididata<$80 then begin
  48.      c:=c+1;
  49.      if c=3 then begin curr_velocity[user_record_trnum]:=mididata;
  50.                        play_herc_lead_sheet
  51.                        (curr_running_status[user_record_trnum],
  52.                       curr_notenum[user_record_trnum],
  53.                       curr_velocity[user_record_trnum]);
  54.                       c:=1;end{IF}
  55.       else  curr_notenum[user_record_trnum]:=mididata ;end;
  56.                       {COULD REDUCE THE IF STATEMENTS }
  57.   if mididata >=$80 then begin
  58.      curr_running_status[user_record_trnum]:=mididata;
  59.      c:=1;end;
  60.  
  61.  
  62. port[$20]:=$20;
  63. inline($07/$1f/$5f/$5e/$5a/$59/$5b/$58/$8b/$e5/$5d/$cf); {cf=interrupt return}
  64. END;
  65. {****************************************************************************}
  66. {****************************************************************************}
  67. procedure init_interrupt(ii:integer);
  68.    {this procedure changes the offset of irq2(=interrupt 10(dec.)) to
  69.     the cseg and offset of the desired interrupt handler }
  70. begin
  71. old_ofs:=memw[$0000:ii*4];
  72. old_seg:=memw[$0000:ii*4+2];
  73. new_ofs:=ofs(never_call_stop_mode_herc); {was mono}
  74. new_seg:=cseg;
  75. memw[$0000:ii*4]:=new_ofs;        {change vector address}
  76. memw[$0000:ii*4+2]:=new_seg;
  77. writeln('prior vector irq',ii:2,' = $',integerhex(old_seg),
  78.                    ':',integerhex(old_ofs));
  79. write('new vector irq',ii:2,' = $',integerhex(new_seg),
  80.                    ':',integerhex(new_ofs));
  81.  
  82. end;
  83. {****************************************************************************}
  84. procedure restore_interrupt(ii:integer);
  85. begin
  86. memw[$0000:ii*4]:=old_ofs;        {change vector address}
  87. memw[$0000:ii*4+2]:=old_seg;
  88. end;
  89. {****************************************************************************}
  90. procedure irq2_on;
  91. begin
  92. write('enabling irq2');
  93. write('  port $21 was ',port[$21]);
  94. init_interrupt(10);
  95. port[$21]:=($fb and port[$21]);   {turns 2nd byte to 0,thus enabling irq2}
  96. end;
  97. {****************************************************************************}
  98. procedure irq2_off;
  99. begin
  100. write(' disabling irq2,port $21 was= ',port[$21]);
  101. port[$21]:= (4 or port[$21]);{turns 2nd byte to 1,thus disabling irq2 }
  102. restore_interrupt(10);
  103. end;
  104. {******************************************}. ... ...-....1200 N81N         ......................... ... ...-....1200 N81N         ....................